<template>
  <div class="flow-designer">
    <div class="designer-header">
      <div class="header-left">
        <h2>流程设计器</h2>
        <span class="flow-info" v-if="currentFlow">{{ currentFlow.flowName }} ({{ currentFlow.flowCode }})</span>
      </div>
      <div class="header-right">
        <el-button @click="saveFlow" type="primary" :icon="DocumentAdd" :loading="saving">
          {{ saving ? '保存中...' : '保存' }}
        </el-button>
        <el-button @click="convertFlow" type="success" :icon="Setting" :loading="converting" :disabled="!currentFlow || !currentFlow.id">
          {{ converting ? '转换中...' : '转换为LiteFlow' }}
        </el-button>
        <el-button @click="previewFlow" :icon="View" :disabled="!hasFlowData">预览规则</el-button>
        <el-divider direction="vertical" />
        <el-button @click="exportFlow" :icon="Download">导出</el-button>
        <el-button @click="importFlow" :icon="Upload">导入</el-button>
        <el-divider direction="vertical" />
        <el-button @click="undo" :icon="RefreshLeft" :disabled="!canUndo">撤销</el-button>
        <el-button @click="redo" :icon="RefreshRight" :disabled="!canRedo">重做</el-button>
        <el-divider direction="vertical" />
        <el-button @click="copySelected" :icon="CopyDocument" :disabled="!selectedElement">复制</el-button>
        <el-button @click="deleteSelected" :icon="Delete" :disabled="!selectedElement">删除</el-button>
        <el-divider direction="vertical" />
        <el-button @click="clearCanvas" :icon="DeleteFilled">清空</el-button>
        <el-divider direction="vertical" />
        <el-button @click="zoomIn" :icon="ZoomIn">放大</el-button>
        <el-button @click="zoomOut" :icon="ZoomOut">缩小</el-button>
        <el-button @click="fitView" :icon="FullScreen">适应画布</el-button>
      </div>
    </div>
    
    <div class="designer-content">
      <!-- 节点面板 -->
      <div class="node-panel">
        <div class="panel-header">
          <h3>节点库</h3>
        </div>
        <div class="panel-content">
          <div v-if="loading" class="loading-container">
            <el-icon class="is-loading"><Loading /></el-icon>
            <p>加载节点库...</p>
          </div>
          <div v-else>
            <!-- 按分类显示节点 -->
            <div 
              v-for="category in nodeCategories" 
              :key="category.name" 
              class="node-category"
              :data-category="category.name"
            >
              <div class="category-header">
                <div class="category-title">
                  <el-icon class="category-icon">
                    <component :is="getCategoryIcon(category.icon)" />
                  </el-icon>
                  <h4>{{ category.label }}</h4>
                  <span class="node-count">({{ category.nodes.length }})</span>
                </div>
                <el-tooltip :content="category.description" placement="top">
                  <el-icon class="info-icon"><InfoFilled /></el-icon>
                </el-tooltip>
              </div>
              <div class="node-list">
                <div 
                  v-for="node in category.nodes" 
                  :key="node.nodeCode"
                  class="node-item"
                  :class="`${node.nodeType.toLowerCase()}-node`"
                  :data-type="node.nodeType.toLowerCase()"
                  :data-code="node.nodeCode"
                  :title="node.description"
                >
                  <div class="node-icon">
                    <el-icon>
                      <component :is="getNodeIcon(node.nodeType)" />
                    </el-icon>
                  </div>
                  <span>{{ node.nodeName }}</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      
      <!-- 画布区域 -->
      <div class="canvas-area">
        <div id="logicflow-container" ref="logicflowContainer"></div>
      </div>
      
      <!-- 属性面板 -->
      <div class="property-panel">
        <div class="panel-header">
          <div class="panel-title">
            <h3>属性配置</h3>
            <el-tag 
              v-if="selectedElement && hasElementChanged()" 
              type="warning" 
              size="small"
              effect="plain"
            >
              未保存
            </el-tag>
          </div>
          <div class="panel-actions" v-if="selectedElement">
            <el-button 
              type="primary" 
              size="small" 
              @click="updateElementProperties"
              :icon="DocumentAdd"
              :disabled="!hasElementChanged()"
            >
              保存配置
            </el-button>
            <el-button 
              type="default" 
              size="small" 
              @click="revertElementProperties"
              :icon="RefreshLeft"
              :disabled="!hasElementChanged()"
            >
              取消修改
            </el-button>
          </div>
        </div>
        <div class="panel-content">
          <div v-if="selectedElement">
            <el-form label-width="80px" size="small">
              <el-form-item label="节点ID">
                <el-input v-model="selectedElement.id" disabled></el-input>
              </el-form-item>
              <el-form-item label="节点类型">
                <el-input v-model="selectedElement.type" disabled></el-input>
              </el-form-item>
              <el-form-item label="节点名称">
                <el-input 
                  v-model="selectedElement.text.value" 
                  @blur="updateElementProperties"
                  placeholder="请输入节点名称"
                ></el-input>
              </el-form-item>
              <el-form-item label="节点编码" v-if="selectedNodeDefinition">
                <el-input 
                  v-model="selectedNodeDefinition.nodeCode" 
                  disabled
                  placeholder="LiteFlow解析标识"
                >
                  <template #suffix>
                    <el-tooltip content="此编码是LiteFlow解析流程的唯一标识" placement="top">
                      <el-icon><InfoFilled /></el-icon>
                    </el-tooltip>
                  </template>
                </el-input>
              </el-form-item>
              
              <!-- 动态属性配置 -->
              <template v-if="selectedNodeConfigSchema">
                <DynamicForm
                  :schema="selectedNodeConfigSchema"
                  :model-value="selectedElement.properties"
                  @update:model-value="updateNodeProperties"
                />
              </template>
              
              <!-- 兜底：显示原有硬编码配置（当没有configSchema时） -->
              <template v-else-if="selectedElement.type === 'http'">
                <el-form-item label="请求URL">
                  <el-input 
                    v-model="selectedElement.properties.url" 
                    @blur="updateElementProperties"
                    placeholder="请输入请求URL"
                  ></el-input>
                </el-form-item>
                <el-form-item label="请求方法">
                  <el-select 
                    v-model="selectedElement.properties.method" 
                    @change="updateElementProperties"
                    style="width: 100%"
                  >
                    <el-option label="GET" value="GET"></el-option>
                    <el-option label="POST" value="POST"></el-option>
                    <el-option label="PUT" value="PUT"></el-option>
                    <el-option label="DELETE" value="DELETE"></el-option>
                  </el-select>
                </el-form-item>
              </template>
              
              <template v-else-if="selectedElement.type === 'script'">
                <el-form-item label="脚本语言">
                  <el-select 
                    v-model="selectedElement.properties.language" 
                    @change="updateElementProperties"
                    style="width: 100%"
                  >
                    <el-option label="JavaScript" value="javascript"></el-option>
                    <el-option label="Python" value="python"></el-option>
                    <el-option label="Groovy" value="groovy"></el-option>
                  </el-select>
                </el-form-item>
                <el-form-item label="脚本内容">
                  <el-input 
                    v-model="selectedElement.properties.script" 
                    @blur="updateElementProperties"
                    type="textarea"
                    :rows="4"
                    placeholder="请输入脚本内容"
                  ></el-input>
                </el-form-item>
              </template>
            </el-form>
          </div>
          <div v-else class="no-selection">
            <p>请选择一个节点或连线</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { 
  DocumentAdd, Delete, ZoomIn, ZoomOut, FullScreen, Download, Upload,
  RefreshLeft, RefreshRight, CopyDocument, DeleteFilled,
  VideoPlay, VideoPause, Link, Document, Setting, View, Loading,
  Folder, EditPen, InfoFilled
} from '@element-plus/icons-vue'
import LogicFlow, { RectNodeModel, RectNode, h } from '@logicflow/core'
import '@logicflow/core/dist/style/index.css'
import { DndPanel } from '@logicflow/extension'
import '@logicflow/extension/lib/style/index.css'
import { saveFlowDesign, getFlowById, convertToLiteFlow, previewLiteFlow } from '@/api/flow'
import { getEnabledNodeDefinitions } from '@/api/nodeDefinition'
import DynamicForm from './components/DynamicForm.vue'

const route = useRoute()

// 响应式数据
const logicflowContainer = ref(null)
const selectedElement = ref(null)
const originalElementData = ref(null) // 存储原始元素数据用于比较
const currentFlow = ref(null)
const canUndo = ref(false)
const canRedo = ref(false)
const saving = ref(false)
const converting = ref(false)
const nodeDefinitions = ref([]) // 节点定义数据
const loading = ref(false) // 加载状态

// 计算属性
const hasFlowData = computed(() => {
  if (!lf) return false
  const data = lf.getGraphData()
  return data.nodes && data.nodes.length > 0
})

// 获取选中节点对应的节点定义
const selectedNodeDefinition = computed(() => {
  if (!selectedElement.value) {
    console.log('selectedNodeDefinition: 没有选中元素')
    return null
  }
  
  console.log('selectedElement完整数据:', selectedElement.value)
  console.log('selectedElement.type:', selectedElement.value.type)
  console.log('selectedElement.properties:', selectedElement.value.properties)
  
  // 优先通过properties.nodeCode匹配
  if (selectedElement.value.properties && selectedElement.value.properties.nodeCode) {
    const nodeCode = selectedElement.value.properties.nodeCode
    console.log('通过nodeCode匹配:', nodeCode)
    const definition = nodeDefinitions.value.find(def => def.nodeCode === nodeCode)
    if (definition) {
      console.log('通过nodeCode找到节点定义:', definition)
      return definition
    }
  }
  
  // 备用方案：通过type字段匹配
  if (selectedElement.value.type) {
    const nodeType = selectedElement.value.type.toUpperCase()
    console.log('通过type匹配:', nodeType)
    const definition = nodeDefinitions.value.find(def => def.nodeType === nodeType)
    if (definition) {
      console.log('通过type找到节点定义:', definition)
      return definition
    }
  }
  
  console.log('未找到匹配的节点定义')
  return null
})

// 获取选中节点的配置Schema
const selectedNodeConfigSchema = computed(() => {
  if (!selectedNodeDefinition.value) {
    console.log('selectedNodeConfigSchema: 没有找到节点定义')
    return null
  }
  
  console.log('selectedNodeDefinition:', selectedNodeDefinition.value)
  // 兼容新旧字段名和格式
  let schema = selectedNodeDefinition.value.configParamsSchema || 
               selectedNodeDefinition.value.configSchema || 
               selectedNodeDefinition.value.nodeConfig || 
               null
  
  // 如果schema是字符串（JSON格式），尝试解析它
  if (typeof schema === 'string') {
    try {
      schema = JSON.parse(schema)
    } catch (e) {
      console.error('解析configSchema失败:', e)
      return null
    }
  }
  
  console.log('selectedNodeConfigSchema:', schema)
  return schema
})


// 节点分类计算属性
const nodeCategories = computed(() => {
  const categories = {
    basic: { 
      name: 'basic', 
      label: '基础节点', 
      icon: 'VideoPlay',
      description: '流程的开始和结束节点',
      nodes: [] 
    },
    control: { 
      name: 'control', 
      label: '控制节点', 
      icon: 'Setting',
      description: '流程控制和条件判断节点',
      nodes: [] 
    },
    process: { 
      name: 'process', 
      label: '业务节点', 
      icon: 'Document',
      description: '业务逻辑处理节点',
      nodes: [] 
    },
    data: { 
      name: 'data', 
      label: '数据节点', 
      icon: 'Folder',
      description: '数据处理和转换节点',
      nodes: [] 
    },
    integration: { 
      name: 'integration', 
      label: '集成节点', 
      icon: 'Link',
      description: '外部系统集成节点',
      nodes: [] 
    },
    script: { 
      name: 'script', 
      label: '脚本节点', 
      icon: 'EditPen',
      description: '脚本执行和自定义逻辑节点',
      nodes: [] 
    }
  }
  
  nodeDefinitions.value.forEach(node => {
    // 优先使用后端category字段，映射到前端分类
    let category
    if (node.category) {
      category = mapCategoryToFrontend(node.category)
    } else {
      // 备用方案：根据节点类型分类
      category = getCategoryByNodeType(node.nodeType)
    }
    
    console.log(`节点 ${node.nodeName} (${node.nodeCode}) - 后端category: ${node.category}, 前端分类: ${category}`)
    
    if (categories[category]) {
      categories[category].nodes.push(node)
    } else {
      // 如果分类不存在，使用默认分类
      console.warn(`未知分类 ${category}，使用默认分类 process`)
      categories['process'].nodes.push(node)
    }
  })
  
  // 只返回有节点的分类，并按优先级排序
  const categoryOrder = ['basic', 'control', 'process', 'data', 'integration', 'script']
  return categoryOrder
    .map(name => categories[name])
    .filter(cat => cat.nodes.length > 0)
})

/**
 * 将后端category映射到前端分类
 * @param {string} category 后端分类
 * @returns {string} 前端分类名称
 */
const mapCategoryToFrontend = (category) => {
  const categoryMapping = {
    // 基础分类
    'BASIC': 'basic',
    // 控制流分类
    'CONTROL': 'control',
    'CONDITION': 'control',
    'FLOW': 'control',
    // 业务节点分类
    'BUSINESS': 'process',
    'SERVICE': 'process',
    // 数据处理分类
    'DATA': 'data',
    'TRANSFORM': 'data',
    'VALIDATION': 'data',
    // 集成分类
    'HTTP': 'integration',
    'API': 'integration',
    'DATABASE': 'integration',
    'MESSAGE': 'integration',
    'TIMER': 'integration',
    // 脚本分类
    'SCRIPT': 'script'
  }
  
  return categoryMapping[category] || 'process' // 默认归类到业务节点
}

/**
 * 根据节点类型获取分类
 * @param {string} nodeType 节点类型
 * @returns {string} 分类名称
 */
const getCategoryByNodeType = (nodeType) => {
  const typeMapping = {
    'START': 'basic',
    'END': 'basic',
    'CONDITION': 'control',
    'PARALLEL': 'control',
    'SWITCH': 'control',
    'LOOP': 'control',
    'HTTP': 'integration',
    'API': 'integration',
    'DATABASE': 'integration',
    'MESSAGE': 'integration',
    'SCRIPT': 'script',
    'GROOVY': 'script',
    'JAVASCRIPT': 'script',
    'PYTHON': 'script',
    'DATA_TRANSFORM': 'data',
    'DATA_FILTER': 'data',
    'DATA_MAPPING': 'data',
    'VALIDATION': 'data',
    'COMMON': 'process',
    'BUSINESS': 'process',
    'SERVICE': 'process'
  }
  
  return typeMapping[nodeType] || 'process'
}

// 获取节点图标的方法
const getNodeIcon = (nodeType) => {
  const iconMap = {
    'START': VideoPlay,
    'END': VideoPause,
    'HTTP': Link,
    'SCRIPT': Document,
    'CONDITION': Setting,
    'COMMON': Document,
    'PARALLEL': View
  }
  return iconMap[nodeType] || Document
}

/**
 * 获取分类图标的方法
 * @param {string} iconName 图标名称
 * @returns {Component} 图标组件
 */
const getCategoryIcon = (iconName) => {
  const iconMap = {
    'VideoPlay': VideoPlay,
    'Setting': Setting,
    'Document': Document,
    'Folder': Folder,
    'Link': Link,
    'EditPen': EditPen
  }
  return iconMap[iconName] || Document
}

// LogicFlow实例
let lf = null
let dndPanel = null

/**
 * 动态创建节点类的工厂函数
 * 根据后端节点定义数据生成对应的LogicFlow节点类
 */
function createDynamicNodeClasses(nodeDefinition) {
  const { nodeCode, nodeName, nodeType, uiConfig } = nodeDefinition
  console.log("创建节点类:", nodeCode, nodeName, nodeType)
  
  // 解析UI配置，设置默认值
  const config = {
    width: 100,
    height: 50,
    radius: 6,
    fill: '#409eff',
    stroke: '#409eff',
    strokeWidth: 2,
    textColor: '#fff',
    fontSize: 12,
    ...uiConfig
  }
  
  // 动态创建Model类
  class DynamicNodeModel extends RectNodeModel {
    initNodeData(data) {
      super.initNodeData(data)
      this.width = config.width
      this.height = config.height
      this.radius = config.radius
      
      // 初始化节点属性
      if (!this.properties) {
        this.properties = {}
      }
      
      // 设置节点编码和名称
      this.properties.nodeCode = nodeCode
      this.properties.nodeName = nodeName
      // 将 nodeType 小写
      this.properties.nodeType = nodeType.toLowerCase()
      
      // 根据节点定义初始化默认属性
      if (nodeDefinition.configParamsSchema) {
        try {
          const schema = typeof nodeDefinition.configParamsSchema === 'string' 
            ? JSON.parse(nodeDefinition.configParamsSchema) 
            : nodeDefinition.configParamsSchema
          
          if (schema && schema.properties) {
            Object.keys(schema.properties).forEach(key => {
              if (!this.properties.hasOwnProperty(key)) {
                const prop = schema.properties[key]
                this.properties[key] = prop.default || ''
              }
            })
          }
        } catch (e) {
          console.warn('解析节点配置Schema失败:', e)
        }
      }
    }
    
    getNodeStyle() {
      return {
        fill: config.fill,
        stroke: config.stroke,
        strokeWidth: config.strokeWidth
      }
    }
  }
  
  // 动态创建View类
  class DynamicNodeView extends RectNode {
    getShape() {
      const { model } = this.props
      const { x, y, width, height, radius } = model
      const style = model.getNodeStyle()
      
      const elements = [
        h('rect', {
          ...style,
          x: x - width / 2,
          y: y - height / 2,
          rx: radius,
          ry: radius,
          width,
          height
        })
      ]
      
      // 添加节点文本
      if (nodeName) {
        elements.push(
          h('text', {
            fill: config.textColor,
            fontSize: config.fontSize,
            x,
            y,
            textAnchor: 'middle',
            dominantBaseline: 'middle'
          }, nodeName)
        )
      }
      
      return h('g', {}, elements)
    }
  }
  
  return {
    Model: DynamicNodeModel,
    View: DynamicNodeView
  }
}

/**
 * 初始化LogicFlow
 */
const initLogicFlow = () => {
  if (!logicflowContainer.value) {
    console.error('LogicFlow容器未找到！')
    return
  }
  
  // 注册DndPanel插件
  LogicFlow.use(DndPanel)
  
  // 获取容器的实际尺寸
  const containerRect = logicflowContainer.value.getBoundingClientRect()
  
  lf = new LogicFlow({
    container: logicflowContainer.value,
    width: containerRect.width || logicflowContainer.value.offsetWidth,
    height: containerRect.height || logicflowContainer.value.offsetHeight,
    grid: {
      size: 20,
      visible: true,
      type: 'dot'
    },
    keyboard: {
      enabled: true
    },
    history: true,
    // 启用拖拽相关配置
    allowRotate: false,
    allowResize: false,
    hoverOutline: false,
    nodeSelectedOutline: false,
    edgeSelectedOutline: false,
    // 启用自动调整画布大小
    autoExpand: true
  })
  
  // 注册自定义节点
  registerCustomNodes()
  
  // 绑定事件
  bindEvents()
  
  // 渲染画布
  lf.render()
  
  // 添加默认开始节点（如果画布为空）
  addDefaultStartNode()
  
  // 确保LogicFlow完全初始化后再设置拖拽面板
  nextTick(() => {
    setupDndPanel()
  })
}

/**
 * 注册自定义节点
 */
/**
 * 动态注册自定义节点
 * 基于后端返回的节点定义数据动态创建和注册节点类
 */
const registerCustomNodes = () => {
  // 遍历所有节点分类和节点定义
  nodeCategories.value.forEach(category => {
    if (category.nodes && Array.isArray(category.nodes)) {
      category.nodes.forEach(nodeDefinition => {
        try {
          console.log('注册节点:', nodeDefinition)
          // 使用动态节点类工厂创建节点类
          const { Model, View } = createDynamicNodeClasses(nodeDefinition)
          
          // 注册节点到LogicFlow
          lf.register({
            type: nodeDefinition.nodeCode, // 使用nodeCode作为节点类型
            view: View,
            model: Model
          })
          
          console.log(`已注册节点: ${nodeDefinition.nodeCode} - ${nodeDefinition.nodeName}`)
        } catch (error) {
          console.error(`注册节点失败: ${nodeDefinition.nodeCode}`, error)
        }
      })
    }
  })
}

/**
 * 配置DnD面板
 */
const setupDndPanel = () => {
  // 使用nextTick确保DOM已更新
  nextTick(() => {
    // 为现有的HTML节点项添加拖拽功能
    const nodeItems = document.querySelectorAll('.node-item')
    console.log('找到节点项数量:', nodeItems.length)
    
    if (nodeItems.length === 0) {
      console.warn('未找到任何节点项，可能DOM还未渲染完成')
      // 延迟重试
      setTimeout(() => {
        setupDndPanel()
      }, 500)
      return
    }
    
    nodeItems.forEach((item, index) => {
      console.log(`配置第${index + 1}个节点项:`, item)
      const nodeType = item.getAttribute('data-type')
      const nodeCode = item.getAttribute('data-code')
      const nodeText = item.querySelector('span').textContent
      
      // 移除之前的事件监听器（如果有）
      if (item._dragHandler) {
        item.removeEventListener('mousedown', item._dragHandler)
      }
      
      // 创建拖拽处理函数
      const dragHandler = (e) => {
        e.preventDefault()
        e.stopPropagation()
        
        // 使用LogicFlow的DnD API开始拖拽
        if (lf && lf.dnd) {
          console.log('开始拖拽节点:', {
            nodeType: nodeType,
            nodeCode: nodeCode,
            nodeText: nodeText
          })
          lf.dnd.startDrag({
            type: nodeCode, // 使用nodeCode作为节点类型，与后端保持一致
            text: nodeText,
            properties: {
              nodeCode: nodeCode,
              nodeName: nodeText,
              nodeType: nodeType
            }
          })
          console.log('拖拽配置完成，type设置为:', nodeCode)
        }
      }
      
      // 保存处理函数引用以便后续移除
      item._dragHandler = dragHandler
      
      // 添加鼠标按下事件
      item.addEventListener('mousedown', dragHandler)
      
      // 添加拖拽样式
      item.style.cursor = 'grab'
      item.style.userSelect = 'none'
      
      // 添加鼠标状态样式
      item.addEventListener('mouseenter', () => {
        if (!item.classList.contains('dragging')) {
          item.style.cursor = 'grab'
        }
      })
      
      item.addEventListener('mousedown', () => {
        item.style.cursor = 'grabbing'
        item.classList.add('dragging')
      })
      
      item.addEventListener('mouseup', () => {
        item.style.cursor = 'grab'
        item.classList.remove('dragging')
      })
      
      // 添加拖拽离开事件
      item.addEventListener('mouseleave', () => {
        item.style.cursor = 'grab'
        item.classList.remove('dragging')
      })
    })
  })
}

/**
 * 绑定事件
 */
const bindEvents = () => {
  // 节点选中事件
  lf.on('node:click', ({ data }) => {
    selectedElement.value = data
    // 保存原始数据用于变化检测
    originalElementData.value = JSON.parse(JSON.stringify(data))
  })
  
  // 边选中事件
  lf.on('edge:click', ({ data }) => {
    selectedElement.value = data
  })
  
  // 画布点击事件
  lf.on('blank:click', () => {
    selectedElement.value = null
  })
  
  // 历史记录变化事件
  lf.on('history:change', ({ data }) => {
    canUndo.value = data.undoAble
    canRedo.value = data.redoAble
  })
  
  // 节点添加事件 - 校验开始节点唯一性
  lf.on('node:add', ({ data }) => {
    console.log('节点添加事件触发:', data)
    console.log('节点类型:', data.type)
    console.log('节点属性:', data.properties)
    
    // 通过nodeType属性识别开始节点
    if (data.properties && data.properties.nodeType === 'START') {
      console.log('检测到开始节点添加，开始校验唯一性')
      validateStartNodeUniqueness(data.id)
    }
  })
  
  // 节点删除事件 - 如果删除的是开始节点且画布为空，重新添加默认开始节点
  lf.on('node:delete', ({ data }) => {
    // 通过nodeType属性识别开始节点
    if (data.properties && data.properties.nodeType === 'START') {
      nextTick(() => {
        const graphData = lf.getGraphData()
        if (!graphData.nodes || graphData.nodes.length === 0) {
          addDefaultStartNode()
        }
      })
    }
  })
}

/**
 * 检测元素属性是否发生变化
 */
const hasElementChanged = () => {
  if (!selectedElement.value || !originalElementData.value) return false
  
  // 比较文本内容
  if (selectedElement.value.text?.value !== originalElementData.value.text?.value) {
    return true
  }
  
  // 比较属性对象
  const currentProps = selectedElement.value.properties || {}
  const originalProps = originalElementData.value.properties || {}
  
  // 简单的深度比较
  return JSON.stringify(currentProps) !== JSON.stringify(originalProps)
}

/**
 * 更新节点属性（动态表单回调）
 * @param {Object} newProperties 新的属性值
 */
const updateNodeProperties = (newProperties) => {
  if (!selectedElement.value) return
  
  // 更新选中元素的属性
  selectedElement.value.properties = { ...newProperties }
  
  // 立即更新到LogicFlow实例
  lf.setProperties(selectedElement.value.id, newProperties)
  
  // 更新原始数据以避免未保存提示
  originalElementData.value = JSON.parse(JSON.stringify(selectedElement.value))
}

/**
 * 更新元素属性（带确认机制）
 */
const updateElementProperties = async () => {
  if (!selectedElement.value) return
  
  // 检测是否有变化
  if (!hasElementChanged()) {
    ElMessage.info('属性未发生变化')
    return
  }
  
  try {
    // 显示确认对话框
    const result = await ElMessageBox.confirm(
      '检测到属性配置已修改，确定要保存吗？',
      '确认保存属性',
      {
        confirmButtonText: '确认保存',
        cancelButtonText: '取消',
        type: 'warning',
        distinguishCancelAndClose: true,
        showCancelButton: true,
        showClose: true
      }
    )
    
    if (result === 'confirm') {
      // 用户确认，保存属性
      lf.setProperties(selectedElement.value.id, selectedElement.value.properties)
      lf.updateText(selectedElement.value.id, selectedElement.value.text.value)
      
      // 更新原始数据
      originalElementData.value = JSON.parse(JSON.stringify(selectedElement.value))
      
      ElMessage.success('属性配置已保存')
    }
  } catch (action) {
    // 用户取消或关闭对话框
    if (action === 'cancel') {
      ElMessage.info('已取消保存')
      // 恢复原始值
      revertElementProperties()
    }
  }
}

/**
 * 恢复元素属性到修改前的状态
 */
const revertElementProperties = () => {
  if (selectedElement.value && originalElementData.value) {
    // 恢复到原始数据
    selectedElement.value = JSON.parse(JSON.stringify(originalElementData.value))
    ElMessage.info('已恢复到修改前的状态')
  }
}

/**
 * 添加默认开始节点
 * 在画布初始化时，如果画布为空则自动添加一个开始节点
 */
const addDefaultStartNode = () => {
  if (!lf) return
  
  const graphData = lf.getGraphData()
  
  // 如果画布为空，添加默认开始节点
  if (!graphData.nodes || graphData.nodes.length === 0) {
    // 查找开始节点定义
    const startNodeDef = nodeDefinitions.value.find(node => 
      node.nodeType === 'START' || node.category === 'BASIC'
    )
    
    // 使用找到的节点定义或默认值
    const nodeCode = startNodeDef ? startNodeDef.nodeCode : 'start'
    const nodeName = startNodeDef ? startNodeDef.nodeName : '开始节点'
    
    const startNode = {
      id: 'start_' + Date.now(),
      type: nodeCode, // 使用nodeCode作为节点类型
      x: 200,
      y: 150,
      text: nodeName,
      properties: {
        nodeCode: nodeCode,
        nodeName: nodeName,
        nodeType: 'START',
        description: '流程开始节点'
      }
    }
    
    lf.addNode(startNode)
    console.log('已添加默认开始节点:', startNode)
  }
}

/**
  * 校验开始节点唯一性
  * 确保画布上只能有一个开始节点
  * @param {string} currentNodeId 当前添加的节点ID
  */
 const validateStartNodeUniqueness = (currentNodeId) => {
   if (!lf) {
     console.log('LogicFlow实例不存在，跳过校验')
     return
   }
   
   const graphData = lf.getGraphData()
   console.log('当前画布数据:', graphData)
   
   // 通过节点属性中的nodeType来识别开始节点，而不是依赖type字段
   const startNodes = graphData.nodes.filter(node => 
     node.properties && node.properties.nodeType === 'START'
   )
   console.log('找到的开始节点:', startNodes)
   console.log('开始节点数量:', startNodes.length)
   console.log('当前节点ID:', currentNodeId)
   
   // 如果有多个开始节点，删除除当前节点外的其他开始节点
   if (startNodes.length > 1) {
     const nodesToDelete = startNodes.filter(node => node.id !== currentNodeId)
     console.log('需要删除的重复开始节点:', nodesToDelete)
     
     nodesToDelete.forEach(node => {
       console.log('删除节点:', node.id)
       lf.deleteNode(node.id)
     })
     
     if (nodesToDelete.length > 0) {
       ElMessage.warning(`已删除 ${nodesToDelete.length} 个重复的开始节点，流程中只能有一个开始节点`)
       console.log('删除重复的开始节点:', nodesToDelete)
     }
   } else {
     console.log('开始节点数量正常，无需删除')
   }
 }
 
 /**
  * 加载数据后校验开始节点
  * 确保加载的流程数据中有且仅有一个开始节点
  */
 const validateStartNodeAfterLoad = () => {
   if (!lf) {
     console.log('LogicFlow实例不存在，跳过加载后校验')
     return
   }
   
   const graphData = lf.getGraphData()
   console.log('加载后校验 - 当前画布数据:', graphData)
   const startNodes = graphData.nodes.filter(node => node.type === 'start')
   console.log('加载后校验 - 找到的开始节点:', startNodes)
   console.log('加载后校验 - 开始节点数量:', startNodes.length)
   
   if (startNodes.length === 0) {
     // 如果没有开始节点，添加一个默认开始节点
     console.log('加载后校验 - 没有开始节点，添加默认开始节点')
     addDefaultStartNode()
     ElMessage.info('已自动添加开始节点')
   } else if (startNodes.length > 1) {
     // 如果有多个开始节点，保留第一个，删除其他的
     const nodesToDelete = startNodes.slice(1)
     console.log('加载后校验 - 需要删除的重复开始节点:', nodesToDelete)
     
     nodesToDelete.forEach(node => {
       console.log('加载后校验 - 删除节点:', node.id)
       lf.deleteNode(node.id)
     })
     
     ElMessage.warning(`检测到多个开始节点，已保留第一个并删除其余 ${nodesToDelete.length} 个重复节点`)
     console.log('删除重复的开始节点:', nodesToDelete)
   }
 }

/**
 * 保存流程
 */
const saveFlow = async () => {
  try {
    saving.value = true
    const flowData = lf.getGraphData()
    
    // 验证流程数据
    if (!flowData.nodes || flowData.nodes.length === 0) {
      const result = await ElMessageBox.confirm(
        '当前流程为空，确定要保存吗？',
        '确认保存',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      )
      if (result !== 'confirm') {
        return
      }
    }
    
    // 如果没有流程ID，提示用户先创建流程
    if (!currentFlow.value || !currentFlow.value.id) {
      ElMessage.warning('请先在流程管理页面创建流程，然后再进行设计和保存')
      return
    }
    
    // 调用API保存流程设计数据
    await saveFlowDesign(currentFlow.value.id, flowData)
    
    // 如果流程不为空，自动转换为LiteFlow脚本并保存到数据库
    if (flowData.nodes && flowData.nodes.length > 0) {
      try {
        console.log('开始自动转换流程为LiteFlow脚本...')
        const convertResponse = await convertToLiteFlow(currentFlow.value.id)
        
        if (convertResponse.code === 200) {
          console.log('LiteFlow脚本转换并保存成功:', convertResponse.data)
          ElMessage.success('流程保存成功，并已自动转换为LiteFlow脚本')
        } else {
          console.warn('LiteFlow脚本转换失败:', convertResponse.message)
          ElMessage.warning(`流程保存成功，但LiteFlow脚本转换失败：${convertResponse.message}`)
        }
      } catch (convertError) {
        console.error('LiteFlow脚本转换过程中发生错误:', convertError)
        ElMessage.warning(`流程保存成功，但LiteFlow脚本转换失败：${convertError.message || '转换过程中发生错误'}`)
      }
    } else {
      ElMessage.success('流程保存成功')
    }
    
    console.log('保存流程数据:', flowData)
    
  } catch (error) {
    if (error !== 'cancel') {
      console.error('保存流程失败:', error)
      ElMessage.error('保存失败：' + (error.message || '未知错误'))
    }
  } finally {
    saving.value = false
  }
}

/**
 * 导出流程
 */
const exportFlow = () => {
  const data = lf.getGraphData()
  const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = 'flow.json'
  a.click()
  URL.revokeObjectURL(url)
}

/**
 * 导入流程
 */
const importFlow = () => {
  const input = document.createElement('input')
  input.type = 'file'
  input.accept = '.json'
  input.onchange = (e) => {
    const file = e.target.files[0]
    if (file) {
      const reader = new FileReader()
      reader.onload = (e) => {
        try {
          const data = JSON.parse(e.target.result)
          lf.render(data)
          ElMessage.success('流程导入成功')
        } catch (error) {
          ElMessage.error('文件格式错误')
        }
      }
      reader.readAsText(file)
    }
  }
  input.click()
}

/**
 * 撤销
 */
const undo = () => {
  lf.undo()
}

/**
 * 重做
 */
const redo = () => {
  lf.redo()
}

/**
 * 复制选中元素
 */
const copySelected = () => {
  if (selectedElement.value) {
    ElMessage.success('复制成功')
  }
}

/**
 * 删除选中元素
 */
const deleteSelected = () => {
  if (selectedElement.value) {
    if (selectedElement.value.type === 'node') {
      lf.deleteNode(selectedElement.value.id)
    } else {
      lf.deleteEdge(selectedElement.value.id)
    }
    selectedElement.value = null
  }
}

/**
 * 清空画布
 */
const clearCanvas = () => {
  lf.clearData()
  selectedElement.value = null
}

/**
 * 放大
 */
const zoomIn = () => {
  lf.zoom(true)
}

/**
 * 缩小
 */
const zoomOut = () => {
  lf.zoom(false)
}

/**
 * 适应画布
 */
const fitView = () => {
  lf.fitView()
}

/**
 * 转换流程为LiteFlow规则
 */
const convertFlow = async () => {
  if (!currentFlow.value || !currentFlow.value.id) {
    ElMessage.warning('请先保存流程后再进行转换')
    return
  }
  
  try {
    converting.value = true
    const flowData = lf.getGraphData()
    if (!flowData || !flowData.nodes || flowData.nodes.length === 0) {
      ElMessage.warning('当前画布没有流程数据，请先设计流程图')
      return
    }
    
    const response = await convertToLiteFlow(currentFlow.value.id)
    
    if (response.code === 200) {
      const result = response.data
      
      // 显示转换结果
      ElMessageBox.alert(
        `<div style="max-height: 400px; overflow-y: auto;">
          <h4>转换成功！</h4>
          <p><strong>EL表达式:</strong></p>
          <pre style="background: #f5f5f5; padding: 10px; border-radius: 4px; font-size: 12px;">${result.elExpression || '无'}</pre>
          <p><strong>节点映射:</strong> ${result.nodeComponentMapping ? Object.keys(result.nodeComponentMapping).length : 0} 个节点</p>
          <p><strong>统计信息:</strong></p>
          <ul>
            <li>总节点数: ${result.statistics?.totalNodes || 0}</li>
            <li>连线总数: ${result.statistics?.totalEdges || 0}</li>
          </ul>
          ${result.warnings && result.warnings.length > 0 ? 
            `<p><strong>警告:</strong></p><ul>${result.warnings.map(w => `<li style="color: #e6a23c;">${w}</li>`).join('')}</ul>` : 
            ''}
        </div>`,
        '转换结果',
        {
          dangerouslyUseHTMLString: true,
          confirmButtonText: '确定'
        }
      )
      
      ElMessage.success('流程已成功转换为LiteFlow规则')
    } else {
      ElMessage.error('转换失败：' + response.message)
    }
  } catch (error) {
    console.error('转换流程失败:', error)
    ElMessage.error('转换失败：' + (error.message || '网络错误'))
  } finally {
    converting.value = false
  }
}

/**
 * 预览LiteFlow规则
 */
const previewFlow = async () => {
  if (!lf) {
    ElMessage.warning('流程设计器未初始化')
    return
  }
  
  const flowData = lf.getGraphData()
  if (!flowData.nodes || flowData.nodes.length === 0) {
    ElMessage.warning('请先设计流程图')
    return
  }
  
  try {
    // 将LogicFlow数据格式转换为后端期望的LogicFlowData格式
    const logicFlowData = {
      flowData: flowData
    }
    const response = await previewLiteFlow(logicFlowData)
    
    if (response.code === 200) {
      const result = response.data
      
      // 显示预览结果
      ElMessageBox.alert(
        `<div style="max-height: 400px; overflow-y: auto;">
          <h4>预览结果</h4>
          <p><strong>EL表达式:</strong></p>
          <pre style="background: #f5f5f5; padding: 10px; border-radius: 4px; font-size: 12px;">${result.elExpression || '无法生成'}</pre>
          <p><strong>节点映射:</strong> ${result.nodeMapping ? Object.keys(result.nodeMapping).length : 0} 个节点</p>
          <p><strong>统计信息:</strong></p>
          <ul>
            <li>总节点数: ${result.statistics?.totalNodes || 0}</li>
            <li>开始节点: ${result.statistics?.startNodes || 0}</li>
            <li>结束节点: ${result.statistics?.endNodes || 0}</li>
            <li>条件节点: ${result.statistics?.conditionNodes || 0}</li>
            <li>并行节点: ${result.statistics?.parallelNodes || 0}</li>
          </ul>
          ${result.warnings && result.warnings.length > 0 ? 
            `<p><strong>警告:</strong></p><ul>${result.warnings.map(w => `<li style="color: #e6a23c;">${w}</li>`).join('')}</ul>` : 
            ''}
        </div>`,
        '预览LiteFlow规则',
        {
          dangerouslyUseHTMLString: true,
          confirmButtonText: '确定'
        }
      )
    } else {
      ElMessage.error('预览失败：' + response.message)
    }
  } catch (error) {
    console.error('预览流程失败:', error)
    ElMessage.error('预览失败：' + (error.message || '网络错误'))
  }
}

/**
 * 加载当前流程信息
 */
const loadCurrentFlow = async () => {
  const flowId = route.params.id
  if (flowId) {
    try {
      const response = await getFlowById(flowId)
      currentFlow.value = response.data
      
      // 如果有流程设计数据，加载到画布
      if (currentFlow.value.flowData) {
        try {
          // 如果flowData是字符串，需要解析为对象
          let flowData = currentFlow.value.flowData
          if (typeof flowData === 'string') {
            flowData = JSON.parse(flowData)
          }
          lf.render(flowData)
          console.log('流程数据加载成功:', flowData)
          
          // 加载数据后校验开始节点
          nextTick(() => {
            validateStartNodeAfterLoad()
          })
        } catch (parseError) {
          console.error('解析流程数据失败:', parseError)
          ElMessage.error('流程数据格式错误，无法加载')
        }
      } else {
        // 如果没有流程数据，添加默认开始节点
        nextTick(() => {
          addDefaultStartNode()
        })
      }
    } catch (error) {
      console.error('加载流程信息失败:', error)
      ElMessage.error('加载流程信息失败：' + (error.message || '未知错误'))
    }
  } else {
    // 如果没有流程ID，创建一个临时流程对象
    currentFlow.value = {
      id: null,
      flowName: '新建流程',
      flowCode: 'new_flow'
    }
  }
}

/**
 * 加载节点定义数据
 */
const loadNodeDefinitions = async () => {
  try {
    loading.value = true
    const response = await getEnabledNodeDefinitions()
    nodeDefinitions.value = response.data || []
    console.log('节点定义数据加载成功:', nodeDefinitions.value)
    
    // 如果后端返回空数据，显示提示信息
    if (nodeDefinitions.value.length === 0) {
      console.warn('后端未返回任何启用的节点定义数据，请检查数据库中的节点定义状态')
      ElMessage.warning('暂无可用的节点定义，请联系管理员配置节点')
    }
  } catch (error) {
    console.error('加载节点定义失败:', error)
    ElMessage.error('加载节点定义失败: ' + (error.message || '未知错误'))
    nodeDefinitions.value = []
  } finally {
    loading.value = false
  }
}

/**
 * 键盘事件处理
 */
const handleKeydown = (event) => {
  // Ctrl+S 保存属性配置
  if (event.ctrlKey && event.key === 's') {
    event.preventDefault()
    if (selectedElement.value && hasElementChanged()) {
      updateElementProperties()
    }
  }
  // Esc 取消修改
  if (event.key === 'Escape') {
    if (selectedElement.value && hasElementChanged()) {
      revertElementProperties()
    }
  }
}

/**
 * 处理窗口大小变化
 */
const handleResize = () => {
  if (lf && logicflowContainer.value) {
    const containerRect = logicflowContainer.value.getBoundingClientRect()
    const newWidth = containerRect.width || logicflowContainer.value.offsetWidth
    const newHeight = containerRect.height || logicflowContainer.value.offsetHeight
    
    // 调整LogicFlow画布尺寸
    lf.resize(newWidth, newHeight)
  }
}

// 组件挂载后初始化
onMounted(() => {
  nextTick(async () => {
    // 先加载节点定义数据
    await loadNodeDefinitions()
    
    // 等待DOM更新后初始化LogicFlow
    await nextTick()
    initLogicFlow()
    
    // 加载流程数据
    await loadCurrentFlow()
    
    // 添加键盘事件监听
    document.addEventListener('keydown', handleKeydown)
    
    // 添加窗口大小变化监听
    window.addEventListener('resize', handleResize)
  })
})

// 组件卸载时清理事件监听
onUnmounted(() => {
  document.removeEventListener('keydown', handleKeydown)
  window.removeEventListener('resize', handleResize)
})
</script>

<style scoped>
.flow-designer {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f5f5f5;
  overflow: hidden; /* 防止整体页面滚动 */
}

.designer-header {
  height: 60px;
  background: #fff;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.header-left h2 {
  margin: 0;
  color: #303133;
  font-size: 18px;
}

.flow-info {
  margin-left: 10px;
  color: #909399;
  font-size: 14px;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.designer-content {
  flex: 1;
  display: flex;
  overflow: hidden;
  min-height: 0; /* 允许flex子项完全收缩 */
}

.node-panel {
  width: 250px;
  background: #fff;
  border-right: 1px solid #e4e7ed;
  display: flex;
  flex-direction: column;
}

.panel-header {
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 15px;
  border-bottom: 1px solid #e4e7ed;
  background: #fafafa;
}

.panel-title {
  display: flex;
  align-items: center;
  gap: 8px;
}

.panel-header h3 {
  margin: 0;
  font-size: 14px;
  color: #303133;
}

.panel-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.panel-content {
  flex: 1;
  padding: 15px;
  overflow-y: auto;
}

.node-category {
  margin-bottom: 24px;
  border: 1px solid #f0f0f0;
  border-radius: 8px;
  overflow: hidden;
  background: #fafafa;
}

.category-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: linear-gradient(135deg, #f8f9fa, #e9ecef);
  border-bottom: 1px solid #e4e7ed;
}

.category-title {
  display: flex;
  align-items: center;
  gap: 8px;
}

.category-icon {
  font-size: 16px;
  color: #409eff;
}

/* 不同分类的主题色 */
.node-category[data-category="basic"] .category-icon {
  color: #67c23a;
}

.node-category[data-category="control"] .category-icon {
  color: #f56c6c;
}

.node-category[data-category="process"] .category-icon {
  color: #409eff;
}

.node-category[data-category="data"] .category-icon {
  color: #e6a23c;
}

.node-category[data-category="integration"] .category-icon {
  color: #9c27b0;
}

.node-category[data-category="script"] .category-icon {
  color: #00bcd4;
}

.node-category[data-category="basic"] .category-header {
  background: linear-gradient(135deg, #f0f9ff, #e6f7ff);
  border-bottom-color: #67c23a;
}

.node-category[data-category="control"] .category-header {
  background: linear-gradient(135deg, #fef0f0, #fde2e2);
  border-bottom-color: #f56c6c;
}

.node-category[data-category="process"] .category-header {
  background: linear-gradient(135deg, #f0f9ff, #e1f3ff);
  border-bottom-color: #409eff;
}

.node-category[data-category="data"] .category-header {
  background: linear-gradient(135deg, #fdf6ec, #faecd8);
  border-bottom-color: #e6a23c;
}

.node-category[data-category="integration"] .category-header {
  background: linear-gradient(135deg, #f3e5f5, #e1bee7);
  border-bottom-color: #9c27b0;
}

.node-category[data-category="script"] .category-header {
  background: linear-gradient(135deg, #e0f2f1, #b2dfdb);
  border-bottom-color: #00bcd4;
}

.node-category h4 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: #303133;
}

.node-count {
  font-size: 12px;
  color: #909399;
  font-weight: normal;
}

.info-icon {
  font-size: 14px;
  color: #909399;
  cursor: help;
  transition: color 0.3s;
}

.info-icon:hover {
  color: #409eff;
}

.node-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px;
  background: #fff;
}

.node-item {
  display: flex;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s ease;
  background: #fff;
  position: relative;
}

.node-item:hover {
  border-color: #409eff;
  background: #f0f9ff;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}

.node-item:active {
  transform: translateY(0);
  box-shadow: 0 1px 4px rgba(64, 158, 255, 0.2);
}

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  color: #666;
}

.loading-container p {
  margin-top: 12px;
  font-size: 14px;
}

.node-item.dragging {
  opacity: 0.8;
  transform: scale(0.95);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.node-item {
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

.node-icon {
  width: 20px;
  height: 20px;
  margin-right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.start-node .node-icon {
  color: #67c23a;
}

.end-node .node-icon {
  color: #f56c6c;
}

.http-node .node-icon {
  color: #409eff;
}

.script-node .node-icon {
  color: #e6a23c;
}

.common-node .node-icon {
  color: #909399;
}

.condition-node .node-icon {
  color: #f56c6c;
}

.parallel-node .node-icon {
  color: #9c27b0;
}

.api-node .node-icon {
  color: #00bcd4;
}

.database-node .node-icon {
  color: #4caf50;
}

.message-node .node-icon {
  color: #ff9800;
}

.data_transform-node .node-icon {
  color: #3f51b5;
}

.data_filter-node .node-icon {
  color: #673ab7;
}

.validation-node .node-icon {
  color: #795548;
}

.business-node .node-icon {
  color: #607d8b;
}

.service-node .node-icon {
  color: #ff5722;
}

.node-item span {
  font-size: 12px;
  color: #303133;
}

.canvas-area {
  flex: 1;
  position: relative;
  background: #fff;
  min-height: 0; /* 确保flex子项能够正确收缩 */
  overflow: hidden; /* 防止内容溢出 */
}

#logicflow-container {
  width: 100%;
  height: 100%;
  min-height: 100%; /* 完全自适应父容器高度 */
}

.property-panel {
  width: 300px;
  background: #fff;
  border-left: 1px solid #e4e7ed;
  display: flex;
  flex-direction: column;
}

.no-selection {
  padding: 20px;
  text-align: center;
  color: #909399;
}

.no-selection p {
  margin: 0;
  font-size: 14px;
}

/* 操作按钮样式优化 */
:deep(.el-button--small) {
  padding: 5px 12px;
  border-radius: 6px;
  font-weight: 500;
  transition: all 0.3s ease;
}

:deep(.el-button--primary) {
  background: linear-gradient(135deg, #409eff, #3a8ee6);
  border: none;
}

:deep(.el-button--success) {
  background: linear-gradient(135deg, #67c23a, #5daf34);
  border: none;
}

:deep(.el-button--danger) {
  background: linear-gradient(135deg, #f56c6c, #f25c5c);
  border: none;
}

:deep(.el-button--warning) {
  background: linear-gradient(135deg, #e6a23c, #d19e2a);
  border: none;
}
</style>